package com.gitee.kamismile.igniteEx.spring.mapper;

import com.gitee.kamismile.igniteEx.common.IginteConfigProperties;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.boot.context.properties.bind.Binder;
import org.springframework.context.*;
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
import org.springframework.core.env.Environment;
import org.springframework.core.io.ResourceLoader;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;


public class MapperScannerRegistrar implements ImportBeanDefinitionRegistrar, ResourceLoaderAware, EnvironmentAware {

    private ResourceLoader resourceLoader;

    private IginteConfigProperties iginteConfigProperties;

    @Override
    public void setEnvironment(Environment environment) {
        this.iginteConfigProperties = Binder.get(environment)
                .bind("spring.ex-ignite", IginteConfigProperties.class).get();
    }

    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
        ClassPathMapperScanner scanner = new ClassPathMapperScanner(registry, iginteConfigProperties);

        // this check is needed in Spring 3.1
        if (resourceLoader != null) {
            scanner.setResourceLoader(resourceLoader);
        }

        Map<String, IginteConfigProperties.ServerProvider> servers = iginteConfigProperties.getServers();

        List<String> basePackages = new ArrayList<>();
        Optional.ofNullable(servers)
                .ifPresent(v -> {
                    List<String> packages = v.keySet().stream()
                            .map(j -> {
                                List<String> list = v.get(j).getBasePackages();
                                if (CollectionUtils.isEmpty(list)) {
                                    return new ArrayList<String>();
                                }
                                return list;
                            })
                            .flatMap(List::stream)
                            .collect(Collectors.toList());
                    basePackages.addAll(packages);
                });

        scanner.registerFilters();
        if (!CollectionUtils.isEmpty(basePackages)) {
            scanner.doScan(StringUtils.toStringArray(basePackages));
        }
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public void setResourceLoader(ResourceLoader resourceLoader) {
        this.resourceLoader = resourceLoader;
    }

}

